/**
 * 
 */
package com.huxi.lang.text;

import java.lang.reflect.Array;
import java.util.Collection;
import java.util.Iterator;
import java.util.Map;
import java.util.Objects;

/**
 * 文本工具单位
 * 
 * @author jian.wu
 *
 */
public abstract class TextUtils {

	/**
	 * 计算字符串长度
	 * 
	 * @param cs 字符串
	 * @return 字符串长度，字符串为空值时返回0。
	 */
	public static int length(final CharSequence cs) {
		return cs == null ? 0 : cs.length();
	}

	@SuppressWarnings("rawtypes")
	public static int length(final Object o) {
		if (o == null) {
			return 0;
		}
		if (o instanceof CharSequence) {
			return ((CharSequence) o).length();
		}
		if (o instanceof Collection) {
			return ((Collection) o).size();
		}
		if (o instanceof Map) {
			return ((Map) o).size();
		}
		if (o.getClass().isArray()) {
			return Array.getLength(o);
		}
		return 1;
	}

	/**
	 * 判断字符串是否空串。
	 * 
	 * @param cs 字符串
	 * @return 空串时返回真，否则返回假。
	 */
	public static boolean isEmpty(final CharSequence cs) {
		return cs == null || cs.length() == 0;
	}

	public static boolean isEmpty(final Object o) {
		return length(o) == 0;
	}

	/**
	 * 判断字符串不是空串。
	 * 
	 * @param cs 字符串
	 * @return 不是空串时返回真，否则返回假。
	 */
	public static boolean isNotEmpty(final CharSequence cs) {
		return !(cs == null || cs.length() == 0);
	}

	public static boolean isNotEmpty(final Object o) {
		return length(o) != 0;
	}

	/**
	 * 判断字符串是否空白串。
	 * 
	 * @param cs 字符串
	 * @return 空白串时返回真，否则返回假。
	 */
	public static boolean isBlank(final CharSequence cs) {
		final int strLen = cs == null ? 0 : cs.length();
		if (strLen == 0) {
			return true;
		}
		for (int i = 0; i < strLen; i++) {
			if (!Character.isWhitespace(cs.charAt(i))) {
				return false;
			}
		}
		return true;
	}

	public static boolean isBlank(final Object o) {
		if (o instanceof CharSequence) {
			return isBlank((CharSequence) o);
		}
		return length(o) == 0;
	}

	/**
	 * 判断字符串不是空白串。
	 * 
	 * @param cs 字符串
	 * @return 空白串时返回真，否则返回假。
	 */
	public static boolean isNotBlank(final CharSequence cs) {
		return !isBlank(cs);
	}

	public static boolean isNotBlank(final Object o) {
		if (o instanceof CharSequence) {
			return !isBlank((CharSequence) o);
		}
		return length(o) != 0;
	}

	/**
	 * 检测文本是否为空串
	 * 
	 * @param <T>
	 * @param text 文本
	 * @return 自身
	 * @throws IllegalArgumentException 文本为空值、空串
	 */
	public static <T> T requireNonEmpty(T text) {
		if (isEmpty(text)) {
			throw new IllegalArgumentException("空字符串");
		}
		return text;
	}

	/**
	 * 检测文本是否为空串
	 * 
	 * @param <T>
	 * @param text    文本
	 * @param message 异常信息
	 * @return 自身
	 * @throws IllegalArgumentException 文本为空值、空串
	 */
	public static <T> T requireNonEmpty(T text, String message) {
		if (isEmpty(text)) {
			throw new IllegalArgumentException(!isEmpty(message) ? message : "空字符串");
		}
		return text;
	}

	/**
	 * 检测文本是否为空白串
	 * 
	 * @param <T>
	 * @param text 文本
	 * @return 自身
	 * @throws IllegalArgumentException 文本为空值、空串、全空白串
	 */
	public static <T> T requireNonBlank(T text) {
		if (isBlank(text)) {
			throw new IllegalArgumentException("空白字符串");
		}
		return text;
	}

	/**
	 * 检测文本是否为空白串
	 * 
	 * @param <T>
	 * @param text    文本
	 * @param message 异常信息
	 * @return 自身
	 * @throws IllegalArgumentException 文本为空值、空串、全空白串
	 */
	public static <T> T requireNonBlank(T text, String message) {
		if (isBlank(text)) {
			throw new IllegalArgumentException(!isEmpty(message) ? message : "空白字符串");
		}
		return text;
	}

	/**
	 * 截断文本，字符数不超过限制长度。
	 * 
	 * @param text   文本
	 * @param limit  限制长度
	 * @param append 超长追加标识
	 * @return 截断后文本
	 */
	public static String trancTextLength(String text, int limit, String append) {
		if (text != null && limit > 0 && text.length() > limit) {
			for (; limit < text.length(); limit++) {
				int code = text.codePointAt(limit);
				if (!Character.isUnicodeIdentifierPart(code)) {
					if (Character.isUnicodeIdentifierStart(code)) {
						return text.substring(0, limit - 1) + append;
					} else {
						return text.substring(0, limit) + append;
					}
				}
			}
		}
		return text;
	}

	/**
	 * 截断文本，字符数不超过限制长度。
	 * 
	 * @param text  文本
	 * @param limit 限制长度
	 * @return 截断后文本
	 */
	public static String trancTextLength(String text, int limit) {
		return trancTextLength(text, limit, EMPTY_STRING);
	}

	private static final String EMPTY_STRING = "";

	/**
	 * 连接多个字符串
	 * 
	 * @param delimiter 分割字符
	 * @param args      字符串列表
	 * @return 连接后字符串，非空值。
	 */
	public static String join(String delimiter, Object... args) {
		final int len = args.length;
		if (len == 0) {
			return EMPTY_STRING;
		} else if (len == 1) {
			return Objects.toString(args[0], EMPTY_STRING);
		} else {
			delimiter = Objects.requireNonNull(delimiter, "");
			StringBuilder sb = new StringBuilder().append(Objects.toString(args[0], EMPTY_STRING));
			for (int i = 1; i < len; i++) {
				sb.append(delimiter).append(Objects.toString(args[i], EMPTY_STRING));
			}
			return sb.toString();
		}
	}

	/**
	 * 连接多个字符串
	 * 
	 * @param args      字符串列表
	 * @param delimiter 分割字符，默认为空串。
	 * @return 连接后字符串，非空值。
	 */
	public static String join(String[] args, String delimiter) {
		final int len = args != null ? args.length : 0;
		if (len == 0) {
			return EMPTY_STRING;
		} else if (len == 1) {
			return Objects.toString(args[0], EMPTY_STRING);
		} else {
			delimiter = Objects.requireNonNull(delimiter, "");
			StringBuilder sb = new StringBuilder().append(Objects.toString(args[0], EMPTY_STRING));
			for (int i = 1; i < len; i++) {
				sb.append(delimiter).append(Objects.toString(args[i], EMPTY_STRING));
			}
			return sb.toString();
		}
	}

	/**
	 * 连接多个字符串
	 * 
	 * @param args      字符串列表
	 * @param delimiter 分割字符，默认为空串。
	 * @return 连接后字符串，非空值。
	 */
	public static String join(Collection<?> args, String delimiter) {
		final int len = args != null ? args.size() : 0;
		if (len == 0) {
			return EMPTY_STRING;
		} else if (len == 1) {
			return Objects.toString(args.iterator().next(), EMPTY_STRING);
		} else {
			delimiter = Objects.requireNonNull(delimiter, "");
			Iterator<?> itor = args.iterator();
			StringBuilder sb = new StringBuilder().append(Objects.toString(itor.next(), EMPTY_STRING));
			while (itor.hasNext()) {
				sb.append(delimiter).append(Objects.toString(itor.next(), EMPTY_STRING));
			}
			return sb.toString();
		}
	}

	public static String formatMessage(String pattern, Object... args) {
		return MessageFormatter.format(pattern, args);
	}

	public static String formatUri(String pattern, Map<String, ?> args) {
		return UriFormatter.format(pattern, args);
	}
}
